#ifndef _FUNCTIONS_H_
#define _FUNCTIONS_H_

#include "ListaDinamica.h"
#include "BmpImage.h"
#include "MathLib.h"

#define BLOCKSIZE 65535     /* tamanho do bloco que vai ser lido a cada iteracao do fread */
#define WINDOW 100          /* tamanho da janela que sera usada no vetor de diferencas */
#define CODESIZE 20 		/* tamanho do codigo final do elemento do vetor de diferencas */
#define IMAGESIZE 10000000  /* tamanho estimado da imagem */

typedef struct {
    int ascii;     /* ascii do elemento do vetor de diferencas */
    char binary[9]; /* correspondente binario do ascii acima */
    unsigned short int nbits;   /* numero de bits necessarios para representar o ascii do elemento */
} TypeDiff;

typedef struct {
    TypeDiff diff_elem;       /* elemento do vetor de diferencas */
    char huffman_code[9];      /* codigo de huffman para o elemento */
    char str_code[20];      /* codigo final para escrita no arquivo */
} DiffCode;

typedef struct {
    DiffCode *diffB; 	/*vetor de diferencas para a cor azul (blue) */
    DiffCode *diffG;	/* vetor de diferencas para a cor verde (green) */
    DiffCode *diffR;    /* vetor de diferencas para a cor vermelha (red) */
    unsigned long int size;     /* tamanho dos dados de imagem */
    HuffTree huffrootB;		/* no da arvore de huffman para a cor azul */
    HuffTree huffrootG; 	/* no da arvore de huffman para a cor verde */
    HuffTree huffrootR; 	/*no da arvore de huffman para a cor vermelha */
	char **codeB;		/* codigos de huffman para a cor azul */
	char **codeG; 		/* codigos de huffman para a cor verde */
	char **codeR;		/* codigos de huffman para a cor vermelha */
} FileStruct;

/* Le toda a estrutura da imagem e a imagem em si */
void *ReadImage(char *imagename, Bmp_Image *bmp) {
    FILE *fd = NULL;

    fd = fopen(imagename, "rb");     /* abre o arquivo no modo binario e leitura */
     if(fd == NULL) {
        printf("The image wasn't opened!\n");
        exit(1);
    }
    if(ReadBitmapHeader(fd, bmp) != 0) 		/* le o cabecalho da imagem bitmap */
        exit(1);

    printf("Header:\n");
    printf("sig: %d\tsize: %ld\toffset: %d\n", bmp->header.sig, bmp->header.size, bmp->header.offset);
    printf("InfoHeader:\n");
    printf("size: %d\twidth: %d\theight: %d\tplanes: %d\tbits: %d\tcompress: %d\timagesize: %d\thres: %d\tvres: %d\tncolours: %d\tnicecolours: %d\n", bmp->info_header.infohsize, bmp->info_header.width, bmp->info_header.height, bmp->info_header.num_planes, bmp->info_header.bits, bmp->info_header.compress, bmp->info_header.image_size, bmp->info_header.hres, bmp->info_header.vres, bmp->info_header.num_colours, bmp->info_header.num_nicecolours);

    ReadBitmapData(fd, bmp); 	/* le as cores RGB da imagem bitmap */

    fclose(fd);
}

/*Cria efetivamente o codigo de huffman*/
/*level indica a profundidade que estou. Na raiz level = 0.
Os filhos dela 1 e assim por diante*/
void RecursiveGenerateCode(HuffTree root, char *aux, int level, char **code){
	if(root != NULL){
		/*O codigo de huffman eh atribuido quando se chega a folha*/
		if(IsLeaf(root)){
			aux[level] = '\0';
			printf("****************\nFreq: %d\n", root->frequency);
			printf("Symbol: %d\n", root->nbits);
			printf("huffcode: %s\n****************\n", aux);

			code[root->nbits] = (char*) malloc(sizeof(char)*(strlen(aux)+1));
			strcpy(code[root->nbits], aux);
		}/*fim if*/

		/*caminhar para a esquerda code=1*/
		aux[level] = '1';
		RecursiveGenerateCode(GetLeft(root), aux, level+1, code);

		/*caminhar para a direita code=0*/
		aux[level] = '0';
		RecursiveGenerateCode(GetRight(root), aux, level+1, code);

	}/*fim if*/
}

/* Gera o codigo de huffman de acordo com a arvore de huffman */
char **GenerateHuffCode(HuffTree root) {
	char *aux = NULL;
	char **code = NULL;
	int i;

	code = (char**) calloc(9, sizeof(char*) );
	aux = (char*) calloc(10, sizeof(char));
	RecursiveGenerateCode(root, aux, 0, code);
	free(aux);

	return code;
}

/* Calcula o vetor de diferencas */
void CreateDiffCode(FileStruct *image, Bmp_Image *bmp) {
    unsigned register int i, j;
    unsigned int count = 0;

	image->size = bmp->info_header.image_size;
    image->diffB = (DiffCode*)calloc(image->size*sizeof(DiffCode)); 	/* aloca memoria para o vetor de diferencas */
    image->diffG = (DiffCode*)calloc(image->size*sizeof(DiffCode));
    image->diffR = (DiffCode*)calloc(image->size*sizeof(DiffCode));

    for(i = 0; i < bmp->info_header.height; i++) {
		for(j = 0; j < bmp->info_header.width; j++) {
		    if(count%WINDOW == 0) { 		/* se alcancou o tamanho da janela, entao pega o valor do proprio ascii */
                image->diffB[count].diff_elem.ascii = toascii(bmp->B[j][i]);
                image->diffG[count].diff_elem.ascii = toascii(bmp->G[j][i]);
                image->diffR[count].diff_elem.ascii = toascii(bmp->R[j][i]);
            } else { 	/* senao aplica diferencas entre os ascii */
                if(j > 0) {
                    image->diffB[count].diff_elem.ascii = toascii(bmp->B[j][i]) - toascii(bmp->B[j-1][i]);
                    image->diffG[count].diff_elem.ascii = toascii(bmp->G[j][i]) - toascii(bmp->G[j-1][i]);
                    image->diffR[count].diff_elem.ascii = toascii(bmp->R[j][i]) - toascii(bmp->R[j-1][i]);
                } else { /* conforme for a posicao da matriz, o valor anterior esta em uma posicao especifica  */
                    image->diffB[count].diff_elem.ascii = toascii(bmp->B[j][i]) - toascii(bmp->B[bmp->info_header.width-1][i-1]);
                    image->diffG[count].diff_elem.ascii = toascii(bmp->G[j][i]) - toascii(bmp->G[bmp->info_header.width-1][i-1]);
                    image->diffR[count].diff_elem.ascii = toascii(bmp->R[j][i]) - toascii(bmp->R[bmp->info_header.width-1][i-1]);
                }
            }
			/* calcula o numero de bits e o valor binario do elemento da diferenca */
            image->diffB[count].diff_elem.nbits = numberOfBits(image->diffB[count].diff_elem.ascii);
            strcpy(image->diffB[count].diff_elem.binary, decToBin(image->diffB[count].diff_elem.ascii));
            image->diffG[count].diff_elem.nbits = numberOfBits(image->diffG[count].diff_elem.ascii);
            strcpy(image->diffG[count].diff_elem.binary, decToBin(image->diffG[count].diff_elem.ascii));
            image->diffR[count].diff_elem.nbits = numberOfBits(image->diffR[count].diff_elem.ascii);
            strcpy(image->diffR[count].diff_elem.binary, decToBin(image->diffR[count].diff_elem.ascii));
            count++;
		}
	}
}

/* Cria a arvore de Huffman com base no vetor de diferencas (incompleto) */
void HuffmanTree(FileStruct *image, Bmp_Image *bmp) {
    unsigned register int i;
    HuffTree auxl, auxr, *huffB, *huffG, *huffR;    /* ponteiros para as subarvores esquerda e direita */
    TipoLista lista;    /* TAD para executar o algoritmo de Huffman */
    /* count: indice que controla o no que sera usado
    pos: indice para remover um no da lista
    freql e freqr: frequencias do no esquerdo e no direito */
    int count, pos, freql, freqr, nbits;
    unsigned long int *freq_bitsB = calloc(9, sizeof(unsigned long int)); /* vetor de frequencia do numero de bits */
    unsigned long int *freq_bitsG = calloc(9, sizeof(unsigned long int));
    unsigned long int *freq_bitsR = calloc(9, sizeof(unsigned long int));

	CreateDiffCode(image, bmp);
    for(i = 0; i < image->size; i++) {	/* conta a frequencia da quantidade de bits */
        nbits = image->diffB[i].diff_elem.nbits;
        freq_bitsB[nbits]++;
        nbits = image->diffG[i].diff_elem.nbits;
        freq_bitsG[nbits]++;
        nbits = image->diffR[i].diff_elem.nbits;
        freq_bitsR[nbits]++;
    }
    huffB = malloc((2*9-1)*sizeof(HuffTree));
    huffG = malloc((2*9-1)*sizeof(HuffTree));
    huffR = malloc((2*9-1)*sizeof(HuffTree));
    lista = IniciaLista();
    for(i = 0; i < 9; i++) {  /* para cada no com frequencia definida (nos folhas), a frequencia e o numero de bits sao setados */
        if(freq_bitsB[i] > 0) {
            huffB[i] = NewTree();
            SetFrequency(huffB[i], freq_bitsB[i]);
            SetSymbol(huffB[i], i);
            InsereUltimoLista(lista, huffB[i]);
        }
    }
    count = i;
    do {    /* algoritmo de Huffman. Ao final desse loop, tem-se o no raiz da arvore de huffman para a cor azul */
        huffB[count] = NewTree();
        auxl = PesquisaMinimo(lista, &pos);
        RemoveDeLista(lista, pos);
        auxr = PesquisaMinimo(lista, &pos);
        RemoveDeLista(lista, pos);
        freql = GetFrequency(auxl);
        freqr = GetFrequency(auxr);
        SetFrequency(huffB[count], freql+freqr);
        SetLeft(huffB[count], auxl);
        SetRight(huffB[count], auxr);
        InsereUltimoLista(lista, huffB[count]);
        count++;
    } while(TamanhoLista(lista) > 1);

    count--;
    image->huffrootB = huffB[count];
    DestroiLista(lista);

    lista = IniciaLista();
    for(i = 0; i < 9; i++) {  /* para cada no com frequencia definida (nos folhas), a frequencia e o numero de bits sao setados */
        if(freq_bitsG[i] > 0) {
            huffG[i] = NewTree();
            SetFrequency(huffG[i], freq_bitsG[i]);
            SetSymbol(huffG[i], i);
            InsereUltimoLista(lista, huffG[i]);
        }
    }
    count = i;
    do {    /* algoritmo de Huffman. Ao final desse loop, tem-se o no raiz da arvore de huffman para a cor verde */
        huffG[count] = NewTree();
        auxl = PesquisaMinimo(lista, &pos);
        RemoveDeLista(lista, pos);
        auxr = PesquisaMinimo(lista, &pos);
        RemoveDeLista(lista, pos);
        freql = GetFrequency(auxl);
        freqr = GetFrequency(auxr);
        SetFrequency(huffG[count], freql+freqr);
        SetLeft(huffG[count], auxl);
        SetRight(huffG[count], auxr);
        InsereUltimoLista(lista, huffG[count]);
        count++;
    } while(TamanhoLista(lista) > 1);

    count--;
    image->huffrootG = huffG[count];
    DestroiLista(lista);

    lista = IniciaLista();
    for(i = 0; i < 9; i++) {  /* para cada no com frequencia definida (nos folhas), a frequencia e o numero de bits sao setados */
        if(freq_bitsR[i] > 0) {
            huffR[i] = NewTree();
            SetFrequency(huffR[i], freq_bitsR[i]);
            SetSymbol(huffR[i], i);
            InsereUltimoLista(lista, huffR[i]);
        }
    }
    count = i;
    do {    /* algoritmo de Huffman. Ao final desse loop, tem-se o no raiz da arvore de huffman para a cor vermelha */
        huffR[count] = NewTree();
        auxl = PesquisaMinimo(lista, &pos);
        RemoveDeLista(lista, pos);
        auxr = PesquisaMinimo(lista, &pos);
        RemoveDeLista(lista, pos);
        freql = GetFrequency(auxl);
        freqr = GetFrequency(auxr);
        SetFrequency(huffR[count], freql+freqr);
        SetLeft(huffR[count], auxl);
        SetRight(huffR[count], auxr);
        InsereUltimoLista(lista, huffR[count]);
        count++;
    } while(TamanhoLista(lista) > 1);

    count--;
    image->huffrootR = huffR[count];
    DestroiLista(lista);

	image->codeB = GenerateHuffCode(image->huffrootB); 	/* gera os codigos de huffman para cada cor */
	image->codeG = GenerateHuffCode(image->huffrootG);
	image->codeR = GenerateHuffCode(image->huffrootR);

	for(i = 0; i < 9; i++) 
		printf("codeB[%d]: %s\tcodeG[%d]: %s\tcodeR[%d]: %s\n", i, image->codeB[i], i, image->codeG[i], i, image->codeR[i]);
}
/*
Cria e escreve no arquivo *file, o codigo *code e os valores da arvore de huffman **codeHuffman*/
void WriteFileCode(char *code, char *filein, FileStruct *f, Bmp_Image *bmp){
	unsigned int i, flag = 0, pos = 0, count = 0;
	unsigned long int size;
	char remainder[2], c;
	unsigned char *aux = NULL;
	unsigned char *aux2 = NULL;
	unsigned char *auxHuff = NULL;
	unsigned char aux3[6];
	FILE *fp = NULL;
	char *fileout = (char*)calloc((strlen(filein)+5)*sizeof(char));
	char *header = (char*)calloc(55*sizeof(char));

	strcpy(fileout, filein);
	strcat(fileout, ".bin");
	fp = fopen(filein, "rb");
	ReadBitmapHeader(fp, bmp);
	fclose(fp);
	/*cria um novo arquivo para a escrita*/
	fp = fopen(fileout, "wb");
	if(fp == NULL){ fprintf(stderr, "Nao foi possivel criar o arquivo final\n"); exit(1); }
	
	/********************cria o cabecalho do arquivo*****************/
	
	/*1)Coloca o tamanho de bits uteis no ultimo byte e */
	size = (unsigned long int) strlen(code);
	sprintf(remainder, "%lu", size % 8); /*para saber quanto bits ignorar no ultimo byte*/
	fwrite(remainder, sizeof(char), 1, fp);/*escreve no arquivo essa quantidade*/

	/*Matriz BLUE*/
	/*2.1)Coloca a arvore de huffman na arvore*/
	auxHuff = (char*)calloc(1, sizeof(char));
	auxHuff[0] = '\0';
	
	/*cada codigo de huffman eh separado por ';'*/
	for(i = 0; i < 9; i++){
		if(f->codeB[i] != NULL){/*verifica se existe o codigo de huffman*/
			sprintf(aux3, "%d;", binToDec(f->codeB[i]));/*Escreve o valor decimal do codigo de huffman*/
			auxHuff = realloc(auxHuff, sizeof(char)*(strlen(auxHuff)+strlen(aux3)+1));
			strcat(auxHuff, aux3);
		}/*fim if NULL*/
		else{/*Se nao existir o codigo para a qtdade i de bits, coloca-se apenas o separador ';' */
			auxHuff = realloc(auxHuff, sizeof(char)*(strlen(auxHuff)+2));
			strcat(auxHuff, ";");
		}/*fim else*/
	}/*fim for*/
	
	fwrite(auxHuff, sizeof(char), strlen(auxHuff), fp);

	free(auxHuff);
	/*Matriz GREEN*/
	
	/*2.2)Coloca a arvore de huffman na arvore*/
	
	auxHuff = (char*)calloc(1, sizeof(char));
	auxHuff[0] = '\0';
	
	/*cada codigo de huffman eh separado por ';'*/
	for(i = 0; i < 9; i++){
		if(f->codeG[i] != NULL){/*verifica se existe o codigo de huffman*/
			sprintf(aux3, "%d;", binToDec(f->codeG[i]));/*Escreve o valor decimal do codigo de huffman*/
			auxHuff = realloc(auxHuff, sizeof(char)*(strlen(auxHuff)+strlen(aux3)+1));
			strcat(auxHuff, aux3);
		}/*fim if NULL*/
		else{/*Se nao existir o codigo para a qtdade i de bits, coloca-se apenas o separador ';' */
			auxHuff = realloc(auxHuff, sizeof(char)*(strlen(auxHuff)+2));
			strcat(auxHuff, ";");
		}/*fim else*/
	}/*fim for*/
	
	fwrite(auxHuff, sizeof(char), strlen(auxHuff), fp);
	
	free(auxHuff);
	
	/*Matriz RED*/
	/*2)Coloca a arvore de huffman na arvore*/
	
	auxHuff = (char*)calloc(1, sizeof(char));
	auxHuff[0] = '\0';
	
	/*cada codigo de huffman eh separado por ';'*/
	for(i = 0; i < 9; i++){
		if(f->codeR[i] != NULL){/*verifica se existe o codigo de huffman*/
			sprintf(aux3, "%d;", binToDec(f->codeR[i]));/*Escreve o valor decimal do codigo de huffman*/
			auxHuff = realloc(auxHuff, sizeof(char)*(strlen(auxHuff)+strlen(aux3)+1));
			strcat(auxHuff, aux3);
		}/*fim if NULL*/
		else{/*Se nao existir o codigo para a qtdade i de bits, coloca-se apenas o separador ';' */
			auxHuff = realloc(auxHuff, sizeof(char)*(strlen(auxHuff)+2));
			strcat(auxHuff, ";");
		}/*fim else*/
	}/*fim for*/
	
	fwrite(auxHuff, sizeof(char), strlen(auxHuff), fp);
	
	free(auxHuff);

	/*Escreve o cabecalho do bitmap*/
	WriteBitmapHeader(fp, bmp);
	/***********************Termina o Cabecalho*****************************/
	
	/*iniciando as variaveis*/
	aux = (unsigned char*) calloc(512000, sizeof(char));/*Escrever de 100 em 100 bytes no arquivo*/
	aux2 = (unsigned char*) calloc(9, sizeof(char)); /**/
	aux2[8] = '\0';
	
	do{
		for(i = 0; (i < 512000) && (!flag); i++){
			/*copia de 8 em 8 bits para a aux2*/
			strncpy(aux2, &code[pos], 8);
		/*transforma o valor binario pra decimal e armazena num unsigned char(0-255)*/
			aux[i] = (unsigned char) binToDecPure(aux2);
			pos = pos + 8; /*reposiciona para ler os proximos 8 bits*/
			if(pos > size) flag = 1; /*verifica se acabou a string*/
		}/*fim for*/

		aux[i] = '\0';
		if(!flag)
			fwrite(aux, sizeof(char), 512000, fp); /*escreve 100 bytes no arquivo*/
		else
			fwrite(aux, sizeof(char), i, fp);
	}while(pos < size);

	fclose(fp);
}/*fim WriteFileCode*/


char *GenerateFinalCode(FileStruct *image, Bmp_Image *bmp) {
    unsigned register int i;
    unsigned short int nbitsB, nbitsG, nbitsR;
    char *finalcode = (char*)calloc(3*(image->size)*CODESIZE*sizeof(char));

    for(i = 0; i < image->size; i++) {
        nbitsB = image->diffB[i].diff_elem.nbits;
        nbitsG = image->diffG[i].diff_elem.nbits;
        nbitsR = image->diffR[i].diff_elem.nbits;
        strcpy(image->diffB[i].huffman_code, image->codeB[nbitsB]);
        strcpy(image->diffG[i].huffman_code, image->codeG[nbitsG]);
        strcpy(image->diffR[i].huffman_code, image->codeR[nbitsR]);
        strcpy(image->diffB[i].str_code, image->diffB[i].huffman_code);
        strcpy(image->diffG[i].str_code, image->diffG[i].huffman_code);
        strcpy(image->diffR[i].str_code, image->diffR[i].huffman_code);
        if(nbitsB != 0)
            strcat(image->diffB[i].str_code, image->diffB[i].diff_elem.binary);
		if(nbitsG != 0)
            strcat(image->diffG[i].str_code, image->diffG[i].diff_elem.binary);
		if(nbitsR != 0)
            strcat(image->diffR[i].str_code, image->diffR[i].diff_elem.binary);
        strcat(finalcode, image->diffB[i].str_code);
        strcat(finalcode, image->diffG[i].str_code);
        strcat(finalcode, image->diffR[i].str_code);
    }

    return finalcode;
}

/*
Le arquivo file. Retorna um char* com o codigo em binario e **code contem os valores da arvore de huffman */
char *ReadFileCode(char *file, FileStruct *f, Bmp_Image *bmp){
	FILE *fp = NULL;
	int i, amount;
	char ch[2], aux3[5];
	unsigned char *code = NULL;
	unsigned char *aux = NULL;
	unsigned char *aux2 = NULL;
	int remainder;

	/*Le arquivo com permissao de leitura*/
	fp = fopen(file, "rb");
	if(fp == NULL){ fprintf(stderr, "%s","Nao foi possivel ler arquivo\n"); return NULL; }
	
	/********************le o cabecalho************************************/
	/*le tamanho de bits uteis no ultimo byte*/
	ch[1] = '\0';
	fread(ch, sizeof(char), 1, fp); /*Valor de remainder contida no arquivo*/
	remainder = atoi(ch);

	/*le a arvore de huffman matriz B*/	
	f->codeB = (char**) calloc(9, sizeof(char*));
	for(i = 0; i < 9; i++){
		aux3[0] = '\0';
		
		/*Le ate encontrar um ';'*/
		do{
			fread(ch, sizeof(char), 1, fp);
			strcat(aux3, ch);

		}while(ch[0] != ';');

		/*verifica-se tinha um numero*/
		if(aux3[0] != ';'){
			/*pega o codigo de huffman*/
			f->codeB[i] = (char*) malloc(sizeof(char)*strlen(aux3));
			aux2 = decToBin(atoi(aux3));
			strcpy(f->codeB[i], aux2);
			free(aux2);
		}/*fim if*/
	}/*fim for*/
	
	/*le a arvore de huffman matriz GREEN*/	
	f->codeG = (char**) calloc(9, sizeof(char*));
	for(i = 0; i < 9; i++){
		aux3[0] = '\0';
		
		/*Le ate encontrar um ';'*/
		do{
			fread(ch, sizeof(char), 1, fp);
			strcat(aux3, ch);

		}while(ch[0] != ';');

		/*verifica-se tinha um numero*/
		if(aux3[0] != ';'){
			/*pega o codigo de huffman*/
			f->codeG[i] = (char*) malloc(sizeof(char)*strlen(aux3));
			aux2 = decToBin(atoi(aux3));
			strcpy(f->codeG[i], aux2);
			free(aux2);
		}/*fim if*/
	}/*fim for*/
	
	/*le a arvore de huffman matriz RED*/	
	f->codeR = (char**) calloc(9, sizeof(char*));
	for(i = 0; i < 9; i++){
		aux3[0] = '\0';
		
		/*Le ate encontrar um ';'*/
		do{
			fread(ch, sizeof(char), 1, fp);
			strcat(aux3, ch);

		}while(ch[0] != ';');

		/*verifica-se tinha um numero*/
		if(aux3[0] != ';'){
			/*pega o codigo de huffman*/
			f->codeR[i] = (char*) malloc(sizeof(char)*strlen(aux3));
			aux2 = decToBin(atoi(aux3));
			strcpy(f->codeR[i], aux2);
			free(aux2);
		}/*fim if*/
	}/*fim for*/
	
	/*Le o cabecalho bitmap*/
	ReadBitmapHeader(fp, bmp);
	/********************termina de ler o cabecalho************************/
	
	code = (char*) malloc(sizeof(char));
	code[0] = '\0';
	aux = (char*) malloc(sizeof(char) * 512001);

	do{
		
		amount = fread(aux, sizeof(char), 512000, fp); /*le de 100 em 100 do arquivo*/
		aux[amount] = '\0';
		for(i = 0; i < amount; i++){
			aux2 = decToBinPure((int)aux[i]);/*valor binario do decimal lido*/
			code = (char*) realloc(code, (strlen(code) + strlen(aux2) + 1)*sizeof(char));/*realoca o tamanho da string para concatenacao*/
			strcat(code, aux2);/*cocatena o code atua com o lido*/
			free(aux2);
		}/*fim for*/

	}while(!feof(fp));
	fclose(fp);
	
	/*Verificando a quantidade de bits para ignorar*/
	if(remainder != 0){
		char a;
		int size = strlen(code), j = size - 8;

		/*Faz o deslocamento de bits. Ex: para remainder=5 00001011 -> 01011000*/
		for(i = (size-remainder); i < size; i++)
			code[j++] = code[i];

		/*realoca com o tamanho correto, ignorando os bits*/
		code = (char*) realloc(code, sizeof(char)*(size-(9-remainder)));
		code[size-(8-remainder)] = '\0';
	}/*fim if remainder*/

	for(i = 0; i < 9; i++)
		printf("codeB[%d]: %s\tcodeG[%d]: %s\tcodeR[%d]: %s\n", i, f->codeB[i], i, f->codeG[i], i, f->codeR[i]); 	

	return code;

}/*fim ReadFileCode*/

void DecodeFile(FileStruct *image, Bmp_Image *bmp, char *filecode) {
	unsigned register int i;
	char *codeaux = NULL, *p = NULL;
	int max_bitsB=0, max_bitsG=0, max_bitsR=0;
	int  nbitsB, nbitsG, nbitsR, nbits_aux;
	char diff_asciiB=0, diff_asciiG=0, diff_asciiR=0;
	FILE *arq = NULL;
	unsigned long int a=0, b=0;

	bmp->B = (char**)calloc(bmp->info_header.width*sizeof(char*)); 	/* aloca memoria para as matrizes RGB */
	bmp->G = (char**)calloc(bmp->info_header.width*sizeof(char*));
	bmp->R = (char**)calloc(bmp->info_header.width*sizeof(char*));
	for(i = 0; i < bmp->info_header.width; i++) {
	    bmp->B[i] = (char*)calloc(bmp->info_header.height*sizeof(char));
	    bmp->G[i] = (char*)calloc(bmp->info_header.height*sizeof(char));
	    bmp->R[i] = (char*)calloc(bmp->info_header.height*sizeof(char));
	}


	for(i = 0; i < 9; i++) { 	/* verifica qual eh o maior numero de bits envolvido */
		if(image->codeB[i] != NULL)
			nbitsB = strlen(image->codeB[i]);
		if(image->codeG[i] != NULL)
			nbitsG = strlen(image->codeG[i]);
		if(image->codeR[i] != NULL)
			nbitsR = strlen(image->codeR[i]);
		if(nbitsB > max_bitsB)
			max_bitsB = nbitsB;	
		if(nbitsG > max_bitsG)
			max_bitsG = nbitsG;	
		if(nbitsR > max_bitsR)
			max_bitsR = nbitsR;	
	}		
	p = filecode;
	codeaux = (char*)malloc((retornaMaior(max_bitsB, max_bitsG, max_bitsR)+1)*sizeof(char));
	do{	
		strncpy(codeaux, p, max_bitsB); 	/* pega a maxima quantidade de bits do vetor binario (diferencas) para o codigo de huffman */
		codeaux[max_bitsB] = '\0';
		for(i = 0; i < 9; i++) {
			if(image->codeB[i] != NULL) {
				nbitsB = strlen(image->codeB[i]); 
				if(strncmp(codeaux, image->codeB[i], nbitsB) == 0) {	/* compara com os codigos de huffman jah obtidos */
					nbits_aux = i;
					i = 10;
				}
			}
		}
		p += nbitsB;	/* pula os proximos nbitsB bits para poder pegar agora o valor do elemento */
		if(nbits_aux > 0) {
			strncpy(codeaux, p, nbits_aux); 	/* como jah se sabe a quantidade de bits do elemento, entao pega-os e obtem o valor */
			codeaux[nbits_aux] = '\0';
			diff_asciiB += binToDec(codeaux);
		}
		bmp->B[a][b] = diff_asciiB;
		p += nbits_aux;

		strncpy(codeaux, p, max_bitsG); /* idem para as demais cores */
		codeaux[max_bitsG] = '\0';
		for(i = 0; i < 9; i++) {
			if(image->codeG[i] != NULL) {
				nbitsG = strlen(image->codeG[i]);
				if(strncmp(codeaux, image->codeG[i], nbitsG) == 0) {
					nbits_aux = i;
					i = 10;	
				}
			}
		}
		p += nbitsG;
		if(nbits_aux > 0) {
			strncpy(codeaux, p, nbits_aux);
			codeaux[nbits_aux] = '\0';
			diff_asciiG += binToDec(codeaux);
		}
		bmp->G[a][b] = diff_asciiG;
		p += nbits_aux;
		
		strncpy(codeaux, p, max_bitsR);
		codeaux[max_bitsR] = '\0';
		for(i = 0; i < 9; i++) {
			if(image->codeR[i] != NULL) {
				nbitsR = strlen(image->codeR[i]);
				if(strncmp(codeaux, image->codeR[i], nbitsR) == 0) {
					nbits_aux = i;
					i = 10;	
				}
			}
		}
		p += nbitsR;
		if(nbits_aux > 0) {
			strncpy(codeaux, p, nbits_aux);
			codeaux[nbits_aux] = '\0';
			diff_asciiR += binToDec(codeaux);
		}
		bmp->R[a][b] = diff_asciiR;
		p += nbits_aux;
		a++;
		if(a == bmp->info_header.width) {
			a = 0;
			b++;
		}
	} while(p[0] != '\0');

	WriteBitmapImage("image_decoded.bmp", bmp);

	printf("\nimage_decoded.bmp was generated!\n");

	fclose(arq); 

}


#endif
